﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls;
using Microsoft.WindowsMobile.PocketOutlook;
using Silvermoon.Images;
using System.Threading;
using Silvermoon.OpenGL;
using System.Drawing;
using Silvermoon.OpenGL.Native;
using Silvermoon.UI;
using Silvermoon.Windows;
using Silvermoon.Shapes;
using Silvermoon.Animations;
using Silvermoon.Utils;
using Silvermoon.Windows.Styles;
using System.Diagnostics;
using OutlookHub.Utils;
using OutlookHub.Images;
using Silvermoon.Navigation;
using OutlookHub.Controllers;

namespace OutlookHub.Pages
{
    public class ContactPage : Page
    {
        public Command ShowDetailsCommand = new Command();
        private ListViewController<TitleDetailsImageItem, ContactData> controller;
        private ContextMenu itemMenu;
        private int yOffsetLoaded;

        const string groupLetters = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        public static VisualStateManager itemManager = new VisualStateManager(
         new VisualState(VState.Normal,
                new ColorTransition { Property = Control.ColorProperty, Duration = 150 },
                new ColorTransition { Property = Control.TextColorProperty, Duration = 10 }
             ),
        new VisualState(VState.Pressed,
            new ColorTransition { Property = Control.ColorProperty, To = PhoneColors.Accent, Duration = 10 },
            new ColorTransition { Property = Control.TextColorProperty, To = Color.White, Duration = 10 })
    );

        static VisualStateManager itemHeaderManager = new VisualStateManager(
             new VisualState(VState.Normal,
                    new ColorTransition { Property = Control.ColorProperty, Duration = 150 },
                    new ColorTransition { Property = Control.TextColorProperty, Duration = 10 }
             ),
            new VisualState(VState.Pressed,
                new ColorTransition { Property = Control.ColorProperty, To = PhoneColors.Black, Duration = 10 },
                new ColorTransition { Property = Control.TextColorProperty, To = Color.White, Duration = 10 })
            );



        #region fields

        private Toolbar toolbar;
        private Dictionary<Contact, Texture> cachedPictures = new Dictionary<Contact, Texture>();
        private ListView listView;

        #endregion
        #region accessors

        public static PropertyAccessor<ContactPage, int> ListBoxOpacityProperty = PropertyAccessor.Register<ContactPage, int>("ListboxOpacity",
            c => c.ListBoxOpacity,
            (c, v) => c.ListBoxOpacity = v);

        #endregion
        #region ctor//dtor
        public ContactPage()
            : base()
        {
            // initializing the page with the contacts data is a time consuming job, so the page is not disposed when navigating forward to another page:
            KeepAlive = true;
            InitializePage();
        }

        protected override void Dispose(bool dispose)
        {
            DisposeObject(itemMenu);
            DisposeObject(toolbar);
            base.Dispose(dispose);
            foreach (var t in cachedPictures.Values)
            {
                if (t != ImagePool.Contact && t != null) t.Dispose();
            }
            cachedPictures.Clear();
        }

        #endregion
        #region props

        public bool Styled { get; set; }

        public int ListBoxOpacity
        {
            get { return listView.Opacity; }
            set { listView.Opacity = value; }
        }

        #endregion
        #region methods


        private void InitializePage()
        {
            SetTransition(350, TransitionMask.RotateLeftOut, 350, TransitionMask.RotateLeftOut);

            Color = PhoneColors.Dark;
            Title = "CONTACTS";
            listView = new ListView { Margin = new Margin(0, 0, 0, 0), AlwaysShowGroupHeader = true, ContainerMargin = new Margin(0, 0, ListView.ScrollbarWidth, 0), Squeeze = false };
            Controls.Add(listView);
            ListBoxOpacity = 0;
            ShowDetailsCommand.Executed += this.OnShowDetailsCommand;

            itemMenu = new ContextMenu();
            itemMenu.Items.Add(new MenuItem("Delete Contact", OutlookCommands.DeleteContact));

            OutlookCommands.DeleteContact.Executed += new EventHandler<CommandEventArgs>(OnDeleteContact);

        }


        private void OnDeleteContact(object sender, CommandEventArgs e)
        {
            ContactData c = e.Object as ContactData;
            if (c != null)
            {
                controller.RemoveValue(c);
                Window w = e.Owner.GetWindow();
                if (w != null) w.GoBack();
            }
        }

        private void AfterShown()
        {
            Screen.Progress();
            List<ContactData> contacts = ReadOutlookContacts();

            var gen = CreateListViewController();
            controller = gen;
            gen.DataSource = contacts;
            listView.YOffset = yOffsetLoaded;

            IntTransition transiton = new IntTransition { From = 0, To = 255, Delay = 2, Duration = 500, Tracking = TrackMode.Keep, EasingFunction = CircleEase.In };
            ListBoxOpacityProperty.BeginAnimation(this, transiton);
            CreateToolbar();
        }

        private List<ContactData> ReadOutlookContacts()
        {
            List<ContactData> contacts = new List<ContactData>();
            using (OutlookSession session = new OutlookSession())
            {
                ContactFolder folder = session.Contacts;
                foreach (var c in folder.Items)
                {

                    ContactData data = new ContactData { Contact = c, Details = GetContactDetails(c) };
                    contacts.Add(data);
                }
            }
            return contacts;
        }

        private ListViewController<TitleDetailsImageItem, ContactData> CreateListViewController()
        {
            ListViewController<TitleDetailsImageItem, ContactData> controller = new ListViewController<TitleDetailsImageItem, ContactData>(listView);
            controller.UpdateItem += new EventHandler<ItemControlGeneratorEventArgs<TitleDetailsImageItem>>(generator_UpdateControl);
            controller.InitializeItem += new EventHandler<ItemControlGeneratorEventArgs<TitleDetailsImageItem>>(controller_InitializeItem);
            controller.GetDescriptorFromValue += new EventHandler<GroupDescriptorEventArgs<ContactData>>(generator_GetDescriptorFromValue);
            controller.ItemHeight = 120;

            foreach (char c in groupLetters)
            {
                string s = c.ToString();
                controller.GroupDescriptors.Add(new ItemGroupDescriptor<ContactData>(s));
            }
            return controller;
        }

        void controller_InitializeItem(object sender, ItemControlGeneratorEventArgs<TitleDetailsImageItem> e)
        {
            e.Item.CommandRaised += (s, args) => args.Object = (s as Item).DataValue;
            e.Item.ContextMenu = itemMenu;
            e.Item.ImageSize = new Size(76, 76);
            e.Item.Padding = new Margin(4, 4, 8, 0);
            //e.Item.ImageBackground = PhoneColors.Accent;
        }


        void generator_GetDescriptorFromValue(object sender, GroupDescriptorEventArgs<ContactData> e)
        {
            ContactData data = e.Value;
            string fileAs = data.Contact.FileAs;
            char c = fileAs.Length > 0 ? Char.ToUpper(fileAs[0]) : Char.MinValue;

            int index = groupLetters.IndexOf(c);
            if (index < 0) index = 0;
            e.Descriptor = e.GroupDescriptors[index];
        }

        void generator_UpdateControl(object sender, ItemControlGeneratorEventArgs<TitleDetailsImageItem> e)
        {
            var item = e.Item;
            item.TitleFont = FontPool.MediumRegularFont;
            ContactData data = e.Value as ContactData;
            Contact contact = data.Contact;
            item.Title = contact.FileAs;
            //item.Command = OutlookCommands.DeleteContact;
            item.Command = ShowDetailsCommand;

            item.ImageColor = Color.White;
            Texture texture = null;
            if (!cachedPictures.TryGetValue(contact, out texture))
            {
                Image img = contact.Picture;
                texture = img != null ? CreateImage(contact) : ImagePool.Contact;
                cachedPictures.Add(contact, texture);
            }
            item.Image = texture;
            item.Details = data.Details;

        }

        private Texture CreateImage(Contact contact)
        {
            Texture texture = new Texture();
            Image img = contact.Picture;

            int w = img.Width;
            int h = img.Height;
            using (DrawingCanvas canvas = texture.CreateCanvas(64, 64, TextureFormat.RGBA5551, Color.Fuchsia))
            {
                Graphics gfx = canvas.Graphics;
                gfx.Clear(Color.Fuchsia);
                int w0 = 64 * w / h;
                gfx.DrawImage(img, new Rectangle(0, 0, w0, 64), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
            }
            return texture;
        }

        private string GetContactDetails(Contact contact)
        {
            StringBuilder sb = new StringBuilder();
            int n = 0;
            if (contact.Email1Address.Length > 0)
            {
                sb.AppendLine(contact.Email1Address);
                n++;
            }
            if (contact.HomeAddressStreet.Length > 0 && contact.HomeAddressCity.Length > 0)
            {
                n++;
                sb.Append(contact.HomeAddressStreet);
                sb.Append(", ");
                if (contact.HomeAddressPostalCode.Length > 0) sb.Append((contact.HomeAddressPostalCode + " "));
                sb.AppendLine(contact.HomeAddressCity);
            }
            else
            {
                if (contact.HomeAddressStreet.Length > 0)
                {
                    sb.AppendLine(contact.HomeAddressStreet);
                    n++;
                }
                else if (contact.HomeAddressCity.Length > 0)
                {
                    n++;
                    if (contact.HomeAddressPostalCode.Length > 0) sb.Append((contact.HomeAddressPostalCode + " "));
                    sb.AppendLine(contact.HomeAddressCity);
                }
            }
            if (n < 2 && contact.HomeTelephoneNumber.Length > 0) sb.AppendLine(contact.HomeTelephoneNumber);

            return sb.ToString();
        }

        private bool isShown;

        protected override void OnShown()
        {
            base.OnShown();
            SetTransition(350, TransitionMask.Fade, 350, TransitionMask.Fade);
            if (!isShown)
            {
                isShown = true;
                AfterShown();
            }
        }

        private void CreateToolbar()
        {
            Toolbar tb = new Toolbar();
            toolbar = tb;
            ToolbarButton b1 = new ToolbarButton { Content = SysImages.Back };
            ToolbarButton b2 = new ToolbarButton { Content = SysImages.Check };
            b1.Tap += (s, e) => GoBack();
            b2.Tap += (s, e) => (listView.ItemsSource[3] as ListViewGroup).BringItemIntoView(2, true);

            tb.Buttons.AddRange(b1, b2);

            Toolbar = tb;
        }


        private void OnShowDetailsCommand(object sender, CommandEventArgs args)
        {
            Item item = args.Owner as Item;
            ShowDetails(this, args);
            args.Handled = true;
        }

        private void ShowDetails(object sender, CommandEventArgs e)
        {
            ContactData contact = e.Object as ContactData;
            if (contact != null)
            {
                ContactDetailsPage details = new ContactDetailsPage { Styled = this.Styled, Contact = contact };
                this.NavigateTo(details);
            }
        }


        private class bag
        {
            public VisualStateManager Manager;
            public int YOffset;
        }

        public override object OnSaveViewState()
        {
            bag bag = new bag { Manager = TransitionManager, YOffset = listView.YOffset };
            return bag;
        }


        public override void OnLoadViewState(object viewState)
        {
            bag bag = viewState as bag;
            if (bag != null)
            {
                TransitionManager = bag.Manager;
                yOffsetLoaded = bag.YOffset;
            }
        }

        protected override void OnBack(HandledEventArgs e)
        {
            // if the page goes back, it should be destroyed:
            KeepAlive = false;
            SetTransition(350, TransitionMask.RotateLeftIn, 350, TransitionMask.RotateLeftOut);
            base.OnBack(e);
        }

        protected override void OnHome(HandledEventArgs e)
        {
            // if the page goes home, it should be destroyed:
            KeepAlive = false;
            base.OnHome(e);
        }


        #endregion
    }
}
